import json
import requests
from datetime import datetime
from copy import deepcopy
# import sys, os
# sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))

from .base_class import Department, WorkTime, Shift, TimeSection, ShiftStyle, \
    SchedulingStaff, ScheduleUnit, GuaranteeStep, Leave
from .util import message
from .util.fetch_data import get_startwork_date, get_staff_leaveinfo, get_shift_info

# datetime format
datetime_fmt = "%Y-%m-%d %H:%M:%S"
date_fmt = "%Y-%m-%d"


# 输入数据结构转化
def parse_schedule_data(data):    
    start_date = datetime.strptime(data["scopeStart"], "%Y-%m-%d").date()
    end_date = datetime.strptime(data["scopeEnd"], "%Y-%m-%d").date()

    department_list = [
        Department(id=dept["id"], name=dept["departmentName"]) 
        for dept in data["departmentBaseDto"]
    ]

    guarantee_list = [
        GuaranteeStep(
            id=int(gua["id"]),
            name=gua["guaranteeName"],
            department_id=gua["deptId"],
            department_code=gua["guaranteeCode"],
            group_min_employee=gua["min"],
            group_max_employee=gua["max"],
            group=gua["group"]
        )
        for gua in data["guaranteeDto"]
    ]

    tmp_schedule_list = []

    schedule_id = 1
    # 解析主班制
    main_shift_ids = []
    for shift in data["shiftRuleDto"]:
        if not shift["isMain"]:
            continue

        # 查找班制部门信息
        department = None
        for dept in department_list:
            if str(dept.id) == str(shift["deptId"]):
                # 部门信息错误：id不唯一
                if department:
                    msg = deepcopy(message.DEPT_ID_NOT_UNIQUE)
                    msg["resultMessage"] += f": {department.id}, {dept.id}"
                    return None, msg
                department = dept

        main_shift, errMsg = parse_shift(shift)
        if not main_shift:
            # 其他班制信息错误
            return None, errMsg 

        staff_list = []
        for staff in shift["userTeamDtoList"]:
            staff_list.append(SchedulingStaff(
                id=staff["userID"],
                name=staff["cnName"],
                cre_types=[],
                start_date=datetime.strptime(staff["startTime"], "%Y-%m-%d").date(),
                leave_list=staff["leaveDto"]
            ))

        name = f"Schedule_{schedule_id} Dept_{department.name} Name_{shift['name']}"

        tmp_schedule_list.append(ScheduleUnit(
            id=schedule_id,
            name=name,
            start_date = start_date,
            end_date = end_date,
            staff_list=staff_list,
            guarantee_list=guarantee_list,
            department=department,
            main_shift=main_shift,
            aux_shift=None
        ))
        main_shift_ids.append(shift["id"])
        schedule_id += 1

    # 解析副班制
    for shift in data["shiftRuleDto"]:
        if shift["isMain"]:
            continue

        # 副班制数据错误：缺失对应主班制字段
        if not "parentId" in shift.keys():
            msg = deepcopy(message.AUX_SHIFT_ERROR)
            msg["resultMessage"] += f" for Shift: {shift['id']}"           
        
        # 副班制数据错误: 无法找到匹配的主班制
        main_index = main_shift_ids.index(shift["parentId"])
        if main_index == -1:
            msg = deepcopy(message.AUX_SHIFT_ERROR)
            msg["resultMessage"] += f" for Shift: {shift['id']}"
        
        aux_shift, errMsg = parse_shift(shift)
        if not aux_shift:
            # 其他班制信息错误
            return None, errMsg 
        tmp_schedule_list[main_index].aux_shift = aux_shift

    schedule_demands = {
        "start_date": start_date,
        "end_date": end_date,
        "department_list": department_list,
        "guarantee_list": guarantee_list,
        "schedule_list": tmp_schedule_list
    }

    return schedule_demands, None


def parse_shift(shift):
    worktime_list = []
    for wt in shift["workTimeResponseVoList"]:
        time_section_list = []
        for section in wt["timeSectionResponseVoList"]:
            time_section = TimeSection(
                start_time=datetime.strptime(section["startTime"], "%H:%M").time(),
                end_time=datetime.strptime(section["endTime"], "%H:%M").time(),
                is_cross_day=section["beCrossDay"]
            )
            time_section_list.append(time_section)

        worktime = WorkTime(
            id=wt["id"],
            name=wt["name"],
            time_section_list=time_section_list,
            required_staff_cnt=wt["performNum"]
        )
        worktime_list.append(worktime)

    style = None
    if shift["style"] == "组内轮转":
        style = ShiftStyle.Turn
    elif shift["style"] == "固定班制":
        style = ShiftStyle.Static
    else:
        # 班制类型错误：无法识别此类型
        msg = deepcopy(message.SHIFT_STYLE_ERROR)
        msg["resultMessage"] += f": {shift['style']}"
        return None, msg
    
    shift = Shift(
        id=shift["id"],
        name=shift["name"],
        duty_days=shift["term"],
        rest_days=shift["interval"],
        style=style,
        is_main=shift["isMain"],
        worktime_list=worktime_list
    )

    return shift, None


# 排班输入数据检查
def schedule_data_fetch_check(request_data, request_addr, is_data_ol):
    arrangeData = request_data
    print('保存接口调用输入数据')
    timeNow = datetime.now()
    time_special_fmt = "%Y-%m-%d_%H-%M-%S"
    timeNowString = timeNow.strftime(time_special_fmt)
    ip = request_addr
    
    # # 检查资质数据
    # if 'credentialsBaseDto' not in arrangeData.keys():
    #     log_file.write('\t'+'credentialsBaseDto不存在'+'\n')
    #     return None, message.NO_CREDENTIALS

    # # 检查保障环节数据
    # if ('guaranteeDto' not in arrangeData.keys()) or (not arrangeData['guaranteeDto']):
    #     return None, message.NO_GUARANTEES
    
    # 检查部门数据
    if ('departmentBaseDto' not in arrangeData.keys()) or (not arrangeData['departmentBaseDto']):
        return None, message.NO_DEPARTMENTS
    departmentIds = [int(item['id']) for item in arrangeData['departmentBaseDto']]

    # 获取员工开始排班日期
    try:
        res = get_startwork_date(is_data_ol)
    except:
        return None, message.FETCH_STAFF_STARTDATE_ERROR
    startTimeAll = res

    # 获取员工休假信息
    try:
        data = get_staff_leaveinfo(is_data_ol)
    except:
        return None, message.LEAVE_INFO_ERROR

    leave_dict = {}
    for item in data:
        start_time = datetime.strptime(item["startTime"], datetime_fmt)
        end_time = datetime.strptime(item["endTime"], datetime_fmt)

        leave = Leave(
                id=item["id"],
                user_id=item["userId"],
                start_time=start_time,
                end_time=end_time,
                tag_id=item["tagId"],
                tag_name=item["tagName"])

        if item["userId"] not in leave_dict.keys():
            leave_dict["userId"] = [leave]
        else:
            leave_dict["userId"].append(leave)

    # 获取班制信息
    try:
        data = get_shift_info(is_data_ol)
    except:
        return None, message.FETCH_SHIFT_ERROR
    
    # 解析班制数据。每一条数据item是一个班制
    shiftRuleDto = []
    department_match_flag = [False for d in departmentIds]
    for item in data:
        deptId = int(item["deptId"])
        if deptId not in departmentIds:
            continue

        if ("userTeamDtoList" not in item.keys()) or (not item["userTeamDtoList"]):
            msg = deepcopy(message.SHIFT_NO_STAFF_ERROR)
            msg["resultMessage"] += f": {item['id']}"
            return None, msg
            
        if item["userTeamDtoList"]:
            # 每一条数据是符合此班制的一个工作人员
            for staff in item['userTeamDtoList']:
                s_time = get_starttime_by_staff(staff['userID'],startTimeAll)
                if not s_time:
                    msg = deepcopy(message.STAFF_STARTDATE_MATCH_ERROR)
                    msg["resultMessage"] += f": {staff['userID']}"
                    return None, msg
                staff['startTime'] = s_time

                staff["leaveDto"] = []
                if staff["userID"] in leave_dict.keys():
                    staff["leaveDto"] = leave_dict["userID"]

        dept_index_in_list = departmentIds.index(deptId)
        department_match_flag[dept_index_in_list] = True
        shiftRuleDto.append(item)

    # 检查 部门-班制 匹配情况
    empty_dept_str = ""
    for i in range(len(departmentIds)):
        if not department_match_flag[i]:
            empty_dept_str += f"{departmentIds[i]}. Check If There is Duplication"

    if empty_dept_str:
        msg =  deepcopy(message.DEPT_SHIFT_MATCH_ERROR)
        msg["resultMessage"] += f": {empty_dept_str}"
        return None, msg

    arrangeData['shiftRuleDto'] = shiftRuleDto

    # 检查和解析排班日期
    date_fmt = "%Y-%m-%d"
    try:
        datetime.strptime(arrangeData['scopeStart'], date_fmt).date()
    except Exception as e:
        print(e.args)
        print(str(e))
        msg = deepcopy(message.DATE_PARSE_ERROR)
        msg["resultMessage"] += f": {arrangeData['scopeStart']}"
        return None, msg

    try:
        datetime.strptime(arrangeData['scopeEnd'], date_fmt).date()
    except Exception:
        msg = deepcopy(message.DATE_PARSE_ERROR)
        msg["resultMessage"] += f": {arrangeData['scopeEnd']}"
        return None, msg
        
    # # 若航班数据字段缺失或字段格式不符，将flightDto列表设置为空
    # if len(arrangeData['flightDto']) > 0:
    #     firstFlight = arrangeData['flightDto'][0]
    #     field_name = ['id','flightNo','airlineCn','craftModelId','craftSize',
    #                 'regionId','crafttypeId','offset','flightproperty',
    #                 'farseat','reflandingtime','dispatchcategoryId','craftModelCn',
    #                 'craftModelCategory','seatNum','task','taskCN']
    #     field_type = [int,str,str,str,int,
    #                 str,str,int,str,
    #                 str,str,str,str,
    #                 str,str,str,str]
    #     for filed_index in range(len(field_name)):
    #         if field_name[filed_index] not in firstFlight.keys():
    #             log_file.write('\t' + '航班信息缺失字段：' + field_name[filed_index] + '\n')
    #             arrangeData['flightDto'] = []

    #             msg = message.FLIGHT_PARSE_ERROR
    #             msg["resultMessage"] += f": Missing Field {field_name[filed_index]}"
    #             return None, msg

    #         if type(firstFlight[field_name[filed_index]]) is not field_type[filed_index]:
    #             log_file.write('\t' + '航班信息字段' + field_name[filed_index] + '格式错误' + '\n')
    #             arrangeData['flightDto'] = []
                
    #             msg = message.FLIGHT_PARSE_ERROR
    #             msg["resultMessage"] += f": '{field_name[filed_index]}' Wrong Format"
    #             return None, msg

    # with open(dataPath+'modify_request'+timeNowString+'.json','w+',encoding='utf-8') as modify_request_data_file:
    #     json.dump(arrangeData,modify_request_data_file,ensure_ascii=False)
    
    return arrangeData, None


# 解析员工的开始排班日期
def get_starttime_by_staff(staffId,startTimeAll):
    startTimeStaffId = [item['userId'] for item in startTimeAll]
    if staffId not in startTimeStaffId:
        return ''
    staff_index = startTimeStaffId.index(staffId)
    return startTimeAll[staff_index]['relStartTime']


# 解析已有排班数据
def parse_existing_workdata(input_data, unit):
    main_shift, staff_list, areas = unit.main_shift, unit.staff_list, unit.areas
    areaIds = [area.id for area in areas]
    staffIds = [staff.id for staff in staff_list]
    summary = {}
    for index, staff in enumerate(staff_list):
        summary[staff.id] = {
            "staff_index": index,
            "worktime_summary": [0 for shift in main_shift.worktime_list],
            "area_summary": [0 for area in areas]
        }

    for item in input_data:
        if item["userId"] in staffIds:
            for wt_index, wt in enumerate(main_shift.worktime_list):
                ts = wt.time_section_list[0]
                # print(item["id"], item["startTime"], item["endTime"])
                if item["startTime"][-8:] == str(ts.start_time) and \
                        item["endTime"][-8:] == str(ts.end_time):
                    summary[item["userId"]]["worktime_summary"][wt_index] += 1
                    break

            if item.__contains__("areaId") and item["areaId"]:
                area_index = areaIds.index(item["areaId"])
                if area_index != -1:
                    summary[item["userId"]]["area_summary"][area_index] += 1
                else:
                    # TEST: 后期添加，区域信息缺失异常处理代码
                    pass

    summary_list = [None for i in range(len(staff_list))]
    for item in summary.values():
        summary_list[item["staff_index"]] = {
            "worktime_summary": item["worktime_summary"],
            "area_summary": item["area_summary"]
        }

    return summary_list